import { jsonParse } from '@/utils';
import * as fs from './fs-helpers';
import { attachment } from './smap-attachment';
import { getHandles } from './utils';
import type { Geometry } from 'geojson';

export type IDBMarkerManifestRecord = {
  id: string;
  name: string;
  address: string;
  color: string;
  iconImage: string;
  attachmentIds: string[];
  geometry: Geometry;
};

export type IDBAddMarkerParams = Omit<IDBMarkerManifestRecord, 'attachmentIds'> & {
  fileList: { uid: string; file?: File }[];
};

export type IDBEditMarkerParams = IDBAddMarkerParams;

export type IDBFindMarkerParams = {
  id: string;
};

export type IDBFindMarkerData = IDBMarkerManifestRecord & { attachments: { id: string; file: File }[] };

const controller = () => {
  const _getHandles = async () => getHandles('markers');

  const getMainfestJson = async () => {
    const handles = await _getHandles();
    return jsonParse<IDBMarkerManifestRecord[]>(await fs.readFile(await handles.manifest.getFile())) ?? [];
  };

  const add = async (params: IDBAddMarkerParams) => {
    try {
      const files = params.fileList.filter((v) => !!v.file);
      const handles = await _getHandles();
      await attachment.add(files.map((v) => ({ id: v.uid, file: v.file! })));
      const mainfestJson = await getMainfestJson();
      mainfestJson.push({
        id: params.id,
        name: params.name,
        color: params.color,
        iconImage: params.iconImage,
        attachmentIds: files.map((record) => record.uid),
        address: params.address,
        geometry: params.geometry,
      });
      fs.writeFile(handles.manifest, JSON.stringify(mainfestJson));
      return { success: true };
    } catch (e) {
      console.error(e);
      return { success: false, error: '保存失败' };
    }
  };

  const edit = async (params: IDBEditMarkerParams) => {
    try {
      const handles = await _getHandles();
      const mainfestJson = await getMainfestJson();
      const record = mainfestJson.find((v) => v.id === params.id);
      const files = params.fileList.filter((v) => !!v.file);
      if (!record) return { success: false, error: '未找到记录' };
      const deletedAttachmentIds = record.attachmentIds.filter((v) => !files.find((f) => f.uid === v));
      const addFiles = files.filter((f) => !record.attachmentIds.find((v) => v === f.uid));
      await attachment.add(addFiles.map((v) => ({ id: v.uid, file: v.file! })));
      if (deletedAttachmentIds.length) await attachment.delete(deletedAttachmentIds);
      mainfestJson.forEach((v) => {
        if (v.id === params.id) {
          v.name = params.name;
          v.address = params.address;
          v.color = params.color;
          v.iconImage = params.iconImage;
          v.geometry = params.geometry;
          v.attachmentIds = files.map((record) => record.uid);
        }
      });
      await fs.writeFile(handles.manifest, JSON.stringify(mainfestJson));
      return { success: true };
    } catch (e) {
      console.error(e);
      return { success: false, error: '编辑失败' };
    }
  };

  const find = async ({ id }: IDBFindMarkerParams) => {
    try {
      const mainfestJson = await getMainfestJson();
      const record = mainfestJson.find((v) => v.id === id);
      if (!record) return { success: true };
      const res = await attachment.find({ ids: record.attachmentIds });
      const data: IDBFindMarkerData = { ...record, attachments: res?.data ?? [] };
      return { success: true, data };
    } catch (e) {
      console.error(e);
      return { success: false, error: '查找失败' };
    }
  };

  const findAll = async () => {
    try {
      const mainfestJson = await getMainfestJson();
      if (!mainfestJson.length) return { success: true, data: [] };
      const data = await Promise.all(
        mainfestJson.map(async (record) => {
          const res = await attachment.find({ ids: record.attachmentIds });
          const data: IDBFindMarkerData = { ...record, attachments: res?.data ?? [] };
          return data;
        }),
      );
      return { success: true, data };
    } catch (e) {
      console.error(e);
      return { success: false, error: '查找失败' };
    }
  };

  const del = async (id: string) => {
    try {
      const handles = await _getHandles();
      const mainfestJson = await getMainfestJson();
      const record = mainfestJson.find((v) => v.id === id);
      if (!record) return { success: true };
      await attachment.delete(record.attachmentIds);
      await fs.writeFile(handles.manifest, JSON.stringify(mainfestJson.filter((v) => v.id !== id)));
      return { success: true };
    } catch (e) {
      console.error(e);
      return { success: false, error: '删除失败' };
    }
  };
  return { findAll, find, add, delete: del, edit, getHandles: _getHandles };
};

export const marker = controller();
